Add completion for throw keyword#7905
Conversation
rescript
@rescript/darwin-arm64
@rescript/darwin-x64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
analysis/src/CompletionBackEnd.ml
Outdated
| | None -> [])) | ||
|
|
||
| (* Collect exception constructor names from cmt infos. *) | ||
| let exceptions_from_cmt_infos (infos : Cmt_format.cmt_infos) : |
There was a problem hiding this comment.
This part is vibe coded I'm afraid.
Please review it and let me know if there is a better way.
There was a problem hiding this comment.
Can a typed tree AST iterator be used here instead of the hand rolled traversal functions below? Would feel more idiomatic, and make the code clearer as you could just add a visitor for the relevant extension nodes.
analysis/src/CompletionBackEnd.ml
Outdated
| (* Predefined Stdlib/Pervasives exceptions. *) | ||
| let predefined_exceptions : (string * bool) list = | ||
| [ | ||
| ("Not_found", true); |
There was a problem hiding this comment.
There was a problem hiding this comment.
I can't help but wonder whether we should be encouraging using these builtins. They're really just heritage from the OCaml era. So I think a case could be made to not include them at all.
There was a problem hiding this comment.
Pull Request Overview
This PR adds completion support for the throw keyword in ReScript, providing suggestions for both built-in and user-defined exceptions when typing "throw".
- Implements completion functionality that suggests exception constructors when typing "throw"
- Adds logic to extract exception information from compiled module files (CMT)
- Includes predefined standard library exceptions with appropriate argument placeholders
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| analysis/src/CompletionBackEnd.ml | Core implementation of throw completion logic including exception extraction and completion generation |
| tests/analysis_tests/tests/src/Throw.res | Test file with custom exceptions for validation |
| tests/analysis_tests/tests/src/expected/Throw.res.txt | Expected completion output for throw keyword test |
| tests/analysis_tests/tests/src/expected/CompletionJsxProps.res.txt | Updated test expectations including new Throw module |
| tests/analysis_tests/tests/src/expected/Completion.res.txt | Updated test expectations including new Throw module |
| CHANGELOG.md | Documentation of the new feature |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
analysis/src/CompletionBackEnd.ml
Outdated
| (* Predefined Stdlib/Pervasives exceptions. *) | ||
| let predefined_exceptions : (string * bool) list = | ||
| [ | ||
| ("Not_found", true); |
There was a problem hiding this comment.
I can't help but wonder whether we should be encouraging using these builtins. They're really just heritage from the OCaml era. So I think a case could be made to not include them at all.
| match (result, path) with | ||
| | [], [prefix] when Utils.startsWith "throw" prefix -> | ||
| completionsForThrow ~env ~full | ||
| | _ -> result) |
There was a problem hiding this comment.
This should probably be done in a "safer" way that matches by type and not by name. We'd need to check if this thing actually resolves to Pervasives.throw.
Also, why Utils.startsWith? Is it not supposed to be an exact match?
There was a problem hiding this comment.
We'd need to check if this thing actually resolves to Pervasives.throw.
If you only have thr you can't do that.
Also, why Utils.startsWith? Is it not supposed to be an exact match?
As mentioned, I want the completions to show up while I'm typing towards the word throw. Only having it once the full word is typed I find unintuitive.
analysis/src/CompletionBackEnd.ml
Outdated
| | None -> [])) | ||
|
|
||
| (* Collect exception constructor names from cmt infos. *) | ||
| let exceptions_from_cmt_infos (infos : Cmt_format.cmt_infos) : |
There was a problem hiding this comment.
Can a typed tree AST iterator be used here instead of the hand rolled traversal functions below? Would feel more idiomatic, and make the code clearer as you could just add a visitor for the relevant extension nodes.
|
Maybe this should more autocomplete I cannot ever remember those things and I basically want to have something show up when I type the I'm okay with leaving the camels behind. |
mediremi
left a comment
There was a problem hiding this comment.
I agree with showing completions for JsError.throwWithMessage and JsExn.throw in addition to throw 👍
zth
left a comment
There was a problem hiding this comment.
Still some outstanding questions and comments from me. Also, is this just for the throw case, without parenthesis and args? A natural extension of this would be to also complete inside of throw(<com>). Unless that already works ofc.
| match (result, path) with | ||
| | [], [prefix] when Utils.startsWith "throw" prefix -> | ||
| completionsForThrow ~env ~full | ||
| | _ -> result) |
analysis/src/ProcessCmt.ml
Outdated
| (match item.str_desc with | ||
| | Tstr_exception _ -> in_toplevel_exception := true | ||
| | _ -> ()); | ||
| () |
There was a problem hiding this comment.
Why is there an extra unit here...?
analysis/src/ProcessCmt.ml
Outdated
| (match item.sig_desc with | ||
| | Tsig_exception _ -> in_toplevel_exception := true | ||
| | _ -> ()); | ||
| () |
| let module Iter = TypedtreeIter.MakeIterator (struct | ||
| include TypedtreeIter.DefaultIteratorArgument |
There was a problem hiding this comment.
Do we use the functor based approach elsewhere in the code base? Or is there no way for the typed tree to just define a mapper like we do for the AST mapper? I don't remember how this works exactly.
There was a problem hiding this comment.
Yes, this was weird to me as well, it is a departure from what we have on the untyped side, but this seems to be the mapper we have?
| (* Only collect top-level exception declarations (Tstr_exception/Tsig_exception). | ||
| Avoid picking up exceptions from Texp_letexception by tracking context. *) |
There was a problem hiding this comment.
In theory I guess the most robust approach would be to collect and use whatever defined exceptions are in scope at the current position. Collecting at the top level is good and simple, but you could also define them in sub modules, and so on.
It might be worth exploring making exceptions part of the tracked scope instead, and track them just like we track types and values today when doing completion. Then we could just extend the current mechanism a bit, and hopefully get the correct scope tracking for free.
|
Hi @zth, could you have another pass on this? |
Uh oh!
There was an error while loading. Please reload this page.